<script>
import Button from "ant-design-vue/es/button";
import Form from "ant-design-vue/es/form";
import "ant-design-vue/lib/form/style/css";
import "ant-design-vue/lib/button/style/css";
import "./dataForm.less";
import inputs from "./extends";
const { Item } = Form;
import cloneDeep from "lodash/cloneDeep";
export default {
  name: "DataForm",
  components: {
    ...inputs
  },
  props: {
    content: {
      type: Array,
      default: () => []
    },
    colnum: {
      type: Number,
      default: 1
    },
    labelWidth: {
      type: [Number, String],
      default: 140
    },
    submitText: {
      type: String,
      default: "提交"
    },
    resetText: {
      type: String,
      default: "重置"
    },
    readonly: {
      type: Boolean,
      required: false,
      default: true
    },
    showButton: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      form: this.$form.createForm(this),
      formData: {},
      // formContent: {},
      loading: false
    };
  },
  created() {
    this.formContent = cloneDeep(this.content);
  },
  mounted() {
    const focusList = [];
    for (const key in this.$refs) {
      const value = this.$refs[key];
      if (value.setFocus) {
        focusList.push(key);
      }
    }
    this.focusList = focusList;

    // const focusList = this.$refs.map(item => {
    //   console.log(item);
    // });
  },
  computed: {
    formColnumStyle() {
      let str = "";
      for (let i = 0; i < this.colnum; i++) {
        str += " 1fr";
      }
      return str;
    },
    formLabelWidth() {
      if (typeof this.labelWidth === "string") {
        return this.labelWidth;
      }
      return this.labelWidth + "px";
    }
  },
  watch: {
    content() {
      // this.formContent = cloneDeep(arr);
    }
  },
  methods: {
    // 生成表单
    getContent(h) {
      let itemIndex = 0;
      const content = this.content.map(item => {
        const _index = itemIndex;
        itemIndex++;
        let inputNode = "";
        if (item.type === null) {
          return <div class="data-form-item "> </div>;
        } else if (item.slot && this.$slots[item.slot]) {
          inputNode = this.$slots[item.slot];
        } else if (item.slot && this.$scopedSlots[item.slot]) {
          inputNode = this.$scopedSlots[item.slot];
        } else if (item.type == "dropdownPanel") {
          //下拉面板
          inputNode = this.getInputNode(item, _index, h);
          const content = item.content ? item.content : {};
          if (
            content.slot &&
            typeof content.slot == "object" &&
            content.slot.length
          ) {
            content.slot.forEach(el => {
              if (this.$slots[el]) {
                item.content[el] = this.$slots[el];
              }
            });
          } else {
            item.content[content.slot] = this.$slots[content.slot];
          }
        } else {
          inputNode = this.getInputNode(item, _index, h);
        }

        const onItemEnter = () => {
          this.onItemEnter(item, _index);
        };
        const input = <div vOn:keydown_enter={onItemEnter}>{inputNode}</div>;

        let itemStyle = {};
        //列
        if (item.colnum && item.colnum > 1) {
          itemStyle["gridColumn"] = "span " + item.colnum;
        }
        //行
        if (item.rownum && item.rownum > 1) {
          itemStyle["gridRow"] = "span " + item.rownum;
        }
        //隐藏
        if (item.type === "hidden") {
          itemStyle["display"] = "none";
        }

        const isColon = item.colon === false || !item.label ? false : true;

        let label = "";
        let labelWidth = this.formLabelWidth;
        if (item.label !== false) {
          //表单容器内边距偏移label宽度
          itemStyle["paddingLeft"] = labelWidth;
          //是否必填
          let isRequired = false;
          if (item.option && item.option.rules && item.option.rules.length) {
            for (let i = 0; i < item.option.rules.length; i++) {
              const rulesItem = item.option.rules[i];
              if (rulesItem.required) {
                isRequired = true;
                break;
              }
            }
          }
          //标题宽度

          if (item.labelWidth) {
            if (typeof item.labelWidth === "number") {
              labelWidth = item.labelWidth + "px";
            } else {
              labelWidth = item.labelWidth;
            }
          }
          //标题内容
          let labelText = "";
          if (typeof item.label === "function") {
            labelText = [item.label()];
            // console.log(arr);
          } else {
            labelText = item.label;
          }
          label = h(
            "div",
            {
              class: [
                "data-form-item-label",
                { colon: isColon },
                { required: isRequired }
              ],
              style: {
                width: labelWidth
              }
            },
            labelText
          );
        } else {
          labelWidth = "0px";
        }

        const itemOption = {
          props: {
            colon: isColon,
            extra: item.extra
          },
          class: "data-form-item",
          style: itemStyle
        };

        return (
          <Item {...itemOption}>
            <div
              class="data-form-item-wrapper"
              {...{ style: { marginLeft: "-" + labelWidth } }}
            >
              {label}
              <div class="data-form-item-content">{input}</div>
            </div>
          </Item>
        );
      });
      return content;
    },
    // 生成操作按钮
    getActions(h) {
      let buttons = this.$slots.action;
      if (!buttons) {
        const submit = h(
          Button,
          {
            props: {
              type: "primary",
              loading: this.loading
            },
            on: {
              click: () => {
                this.onSubmit();
              }
            }
          },
          this.submitText
        );
        const reset = h(
          Button,
          {
            style: {
              marginLeft: "16px"
            },
            on: {
              click: () => {
                this.reset();
              }
            }
          },
          this.resetText
        );
        buttons = (
          <span class="form-action-box">
            {submit}
            {reset}
          </span>
        );
      }

      return (
        <div
          class="data-form-action"
          {...{ style: { marginLeft: this.formLabelWidth } }}
        >
          {buttons}
        </div>
      );
    },
    // 生成输入元素
    getInputNode(node, index, h) {
      const inputs = {
        input: "FormInput",
        password: "FormPassword",
        textarea: "FormTextarea",
        select: "FormSelect",
        number: "FormNumber",
        cascader: "FormCascader",
        checkbox: "FormCheckbox",
        checkboxGroup: "FormCheckboxGroup",
        radioGroup: "FormRadioGroup",
        date: "FormDatePicker",
        month: "FormMonthPicker",
        week: "FormWeekPicker",
        dateRange: "FormDateRangePicker",
        time: "FormTimePicker",
        timeRange: "FormTimeRangePicker",
        slider: "FormSlider",
        switch: "FormSwitch",
        treeSelect: "FormTreeSelect",
        rate: "FormRate",
        upload: "FormUpload",
        dropdownPanel: "DropDownPanel"
      };

      const vDecorator = [node.name];
      if (node.option) {
        vDecorator.push(node.option);
      }
      const nodeProps = node.props ? node.props : {};
      // if (node.type === "password") {
      //   nodeProps.type = "password";
      // }

      const props = {
        ref: "input_" + index,
        props: {
          ...nodeProps,
          placeholder: node.placeholder,
          option: node
        },
        // style: {
        //   width: node.width ? node.width : "100%"
        // },
        on: {
          ...node.on
        },
        directives: [
          {
            name: "decorator",
            value: vDecorator
          }
        ]
      };

      const type = node.type ? node.type : "input";
      const inputName = inputs[type];

      const input = h(inputName, props);

      return input;
    },
    //回车事件
    onItemEnter(node, _index) {
      //回调
      const refName = "input_" + _index;
      if (node.on && node.on.pressEnter) {
        const input = this.$refs[refName];
        const callRes = node.on.pressEnter(input);
        if (callRes === false) return;
      }

      const index = this.focusList.findIndex(p => p === refName);
      const nextIndex = index + 1;
      if (nextIndex < this.focusList.length) {
        const nextInputRef = this.focusList[nextIndex];
        const nextInput = this.$refs[nextInputRef];
        if (nextInput && nextInput.setFocus) {
          nextInput.setFocus(true);
        }
      }
    },
    // 提交事件
    onSubmit() {
      this.form.validateFields((err, values) => {
        if (!err) {
          //处理数据
          //checkbox 值
          // for (let i = 0; i < this.content.length; i++) {
          //   const item = this.content[i];
          //   if (item.type === "checkbox") {
          //     const trueValue = item.trueValue ? item.trueValue : true;
          //     const falseValue =
          //       item.falseValue || item.falseValue === 0
          //         ? item.falseValue
          //         : false;
          //     values[item.name] = values[item.name] ? trueValue : falseValue;
          //   }
          // }
          this.$emit("submit", values);
        }
      });
    },
    //清空表单
    reset() {
      this.form.resetFields();
    },
    // 获取表单数据，不验证
    getData() {
      // const that = this;
      // if (verify) {
      //   return new Promise((resolve, reject) => {
      //     that.form.validateFields((err, values) => {
      //       if (!err) {
      //         resolve(values);
      //       } else {
      //         reject();
      //       }
      //     });
      //   });
      // } else {
      return this.form.getFieldsValue();
      // }
    },
    // 校验并获取一组输入域的值
    validateFields(fields) {
      return new Promise((resolve, reject) => {
        this.form.validateFields(fields, (err, values) => {
          if (!err) {
            resolve(values);
          } else {
            reject();
          }
        });
      });
    },
    //设置表单数据
    setData(data, all) {
      this.formData = cloneDeep(data);
      //表单所有字段
      const formFields = this.content.map(item => item.name);
      //过滤非表单字段参数
      let formData = {};
      for (const key in this.formData) {
        if (formFields.includes(key)) {
          formData[key] = this.formData[key];
        }
      }
      if (all) {
        const dataKeysArr = Object.keys(formData);
        for (let i = 0; i < formFields.length; i++) {
          const key = formFields[i];
          if (key) {
            if (dataKeysArr.includes(key)) {
              formData[key] = this.formData[key];
            } else {
              formData[key] = "";
            }
          }
        }
      }

      this.$nextTick(() => {
        this.form.setFieldsValue(formData);
      });
    },
    submitLoading(is) {
      this.loading = is;
    }
  },
  render(h) {
    let formContent = this.$slots.default;

    //配置参数生成表单
    if (this.content && this.content.length) {
      formContent = this.getContent(h);
    }

    //提交按钮
    let formActions = "";
    if (this.$listeners.submit && this.showButton !== false) {
      formActions = this.getActions(h);
    }

    const formOption = {
      props: {
        form: this.form
      },
      class: "data-form-form",
      style: {
        "grid-template-columns": this.formColnumStyle
      }
    };

    return (
      <div class="data-form-box">
        <div class="data-form-content">
          <Form {...formOption}>{formContent}</Form>
        </div>
        {formActions}
      </div>
    );
  }
};
</script>
